<?php
/**
 * CControllerConfig class file.
 * 获取或设置控制器配置数据.
 * @author Huan Song <iphper@yeah.net>
 * @version $Id: CControllerConfig.php 1 2011-01-12 22:16:36Z huan.song $
 * @package system.controller
 * @since 2.0
 */
class CControllerConfig extends CConfig
{
	/**
     * @var integer url链接样式index.php?r=controller/action.
     */
	const NORMAL = 1;
	
	/**
     * @var integer url链接样式index.php/controller/action.
     */
	const PATHINFO = 2;
	
	/**
     * @var integer url链接样式website/controller/action.
     */
	const REWRITE = 3;
	
	/**
     * @var array url链接样式 .
     */
	protected static $_urlModels = array(
		self::NORMAL => 'NORMAL', 
		self::PATHINFO => 'PATHINFO', 
		self::REWRITE => 'REWRITE'
	);
	
	/**
	 * 三种单入口URL模式.
	 * Options
	 * NORMAL (1) (default).
	 * PATHINFO (2).
	 * REWRITE (3).
	 * @var integer.
	 */
    protected static $_urlModel;
    
    /**
	 * @var string 控制器名.
	 */
    protected static $_controller;
    
    /**
	 * @var string 控制器默认后缀.
	 */
    protected static $_controllerKey;
	
    /**
	 * @var string 方法名.
	 */
    protected static $_action;
    
    /**
	 * @var string 方法名默认后缀.
	 */
    protected static $_actionKey;

    /**
	 * @var string 如果方法名为空，默认调用的方法名.
	 */
    protected static $_defaultAction;
    
    /**
	 * @var string 如果控制器名为空，默认调用的控制器名.
	 */
    protected static $_defaultController;

    /**
	 * @var string 控制器所在的目录.
	 */
	protected static $_controllerDir;
	
	/**
	 * 获取单入口方式.
	 * <pre>
	 * $urlModel = CControllerConfig::getUrlModel();
	 * </pre>
     * @return string 单入口方式. 共三种, NORMAL(1), PATHINFO(2), REWRITE(3).
     * @see setUrlModel
     */
    public static function getUrlModel()
    {
    	if (null === self::$_urlModel)
    		self::setUrlModel();
    	
    	return self::$_urlModel;
    }
    
    /**
     * 设置单入口方式. 共三种, NORMAL(1), PATHINFO(2), REWRITE(3).
     * <pre>
	 * $urlModel = null;
	 * CControllerConfig::setUrlModel($urlModel);
	 * 如果$urlModel === null, 取配置中
	 * 'controller' => array(
	 * 		'urlModel' => 'REWRITE', //单入口方式. REWRITE = 3, PATHINFO = 2, NORMAL = 1.
	 * 	),
	 * 结果: self::$_urlModel = 3.
	 * </pre>
     * @param string|null $urlModel. 如果为空, 从用户配置中获取; 如果不是以上三种, 默认为NORMAL(1)
     * @see getUrlModel
     */
    public static function setUrlModel($urlModel = null)
    {
    	if (null === $urlModel)
    	{
    		$urlModel = self::get('controller', 'urlModel');
    		if (null === $urlModel)
    			self::$_urlModel = self::NORMAL;
    	}
    	
    	if (!isset(self::$_urlModels[$urlModel]))
    	{
    		if (false === ($urlModel = array_search(strtoupper($urlModel), self::$_urlModels)))
    			$urlModel = self::NORMAL;
    	}
    	
    	self::$_urlModel = (int) $urlModel;
    }
    
    /**
     * 判读URL模式: 是否是NORMAL(1)
     * <pre>
	 * $bool = CControllerConfig::isNormal();
	 * </pre>
     * return boolean.
     */
    public static function isNormal()
    {
    	return self::NORMAL === self::getUrlModel();
    }
    
    /**
     * 判读URL模式: 是否是PATHINFO(2)
     * <pre>
	 * $bool = CControllerConfig::isPathinfo();
	 * </pre>
     * return boolean.
     */
    public static function isPathinfo()
    {
    	return self::PATHINFO === self::getUrlModel();
    }
    
    /**
     * 判读URL模式: 是否是REWRITE(3)
     * <pre>
	 * $bool = CControllerConfig::isRewrite();
	 * </pre>
     * return boolean.
     */
    public static function isRewrite()
    {
    	return self::REWRITE === self::getUrlModel();
    }
    
	/**
	 * 获取控制器文件路径.
	 * <pre>
	 * $controllerFile = CControllerConfig::getControllerFile();
	 * </pre>
	 * @return string 控制器文件路径.
	 * @throws CControllerException. 如果控制器文件路径不存在, 抛出异常.
	 */
	public static function getControllerFile()
	{
		$controllerFile = self::getControllerDir() . DS . self::getControllerClass() . '.php';
		if (!file_exists($controllerFile))
			throw new CControllerException('CControllerConfig:getControllerFile controllerFile not exists', array('{controllerFile}' => $controllerFile));
		
		return $controllerFile;
	}
    
	/**
	 * 获取控制器类名. 控制器名 + 后缀.
	 * <pre>
	 * $controllerClass = CControllerConfig::getControllerClass();
	 * </pre>
	 * @return string 控制器类名.
	 */
	public static function getControllerClass()
	{
		return ucfirst(self::getController()) . self::getControllerKey();
	}
	
	/**
	 * 获取方法名. 方法名 + 后缀.
	 * <pre>
	 * $actionMethod = CControllerConfig::getActionMethod();
	 * </pre>
	 * @return string 方法名.
	 */
	public static function getActionMethod()
	{
		return self::getAction() . self::getActionKey();
	}
	
	/**
	 * 获取控制器名.
	 * <pre>
	 * $controller = CControllerConfig::getController();
	 * </pre>
     * @return string 控制器名.
     * @see setController
     */
    public static function getController()
    {
    	if (null === self::$_controller)
    		self::setController();
    	
    	return self::$_controller;
    }
    
    /**
     * 设置控制器名.
     * <pre>
	 * $controller = null;
	 * CControllerConfig::setController($controller);
	 * 如果$controller === null,
	 * 先获取$_GET['c'], 如果$_GET['c']不存在, 获取$_POST['c'].
	 * 结果: self::$_controller = $_GET['c'].
	 * </pre>
     * @param string|null $controller.
     * @see getController
     */
    public static function setController($controller = null)
    {
    	if (null === $controller)
    	{
    		$controller = CRequest::getInstance()->getParam('c');
    		if (null === $controller)
    			$controller = self::getDefaultController();
    	}
    	
    	self::$_controller = strtolower($controller);
    }
    
    /**
     * 获取控制器默认后缀.
     * <pre>
	 * $controllerKey = CControllerConfig::getControllerKey();
	 * </pre>
     * @return string 控制器默认后缀.
     * @see setControllerKey
     */
    public static function getControllerKey()
    {
    	if (null === self::$_controllerKey)
    		self::setControllerKey();
    	
    	return self::$_controllerKey;
    }
    
    /**
     * 设置控制器默认后缀.
     * <pre>
	 * $controllerKey = null;
	 * CConfig::setControllerKey($controllerKey);
	 * 如果$controllerKey === null, 取配置中
	 * 'controller' => array(
	 * 		'controllerKey' => 'Controller', //控制器默认后缀.
	 * 	),
	 * 结果: self::$_controllerKey = 'Controller'.
	 * </pre>
     * @param string|null $controllerKey.
     * @see getControllerKey
     */
    public static function setControllerKey($controllerKey = null)
    {
    	if (null === $controllerKey)
    	{
    		$controllerKey = self::get('controller', 'controllerKey');
    		if (null === $controllerKey)
    			$controllerKey = 'Controller';
    	}
    	
    	self::$_controllerKey = $controllerKey;
    }
    
    /**
     * 获取方法名.
     * <pre>
	 * $action = CControllerConfig::getAction();
	 * </pre>
     * @return string 方法名.
     * @see setAction
     */
    public static function getAction()
    {
    	if (null === self::$_action)
    		self::setAction();
    	
    	return self::$_action;
    }
    
    /**
     * 设置方法名.
     * <pre>
	 * $action = null;
	 * CControllerConfig::setAction($action);
	 * 如果$action === null,
	 * 先获取$_GET['a'], 如果$_GET['a']不存在, 获取$_POST['a'].
	 * 结果: self::$_action = $_GET['a'].
	 * </pre>
     * @param string|null $action.
     * @see getAction
     */
    public static function setAction($action = null)
    {
    	if (null === $action)
    	{
    		$action = CRequest::getInstance()->getParam('a');
    		if (null === $action)
    			$action = self::getDefaultAction();
    	}
    	
    	self::$_action = strtolower($action);
    }
    
    /**
     * 获取方法名默认后缀.
     * <pre>
	 * $actionKey = CControllerConfig::getActionKey();
	 * </pre>
     * @return string 方法名默认后缀.
     * @see setActionKey
     */
    public static function getActionKey()
    {
    	if (null === self::$_actionKey)
    		self::setActionKey();
    	
    	return self::$_actionKey;
    }
    
    /**
     * 设置方法名默认后缀.
     * <pre>
	 * $actionKey = null;
	 * CControllerConfig::setActionKey($actionKey);
	 * 如果$actionKey === null, 取配置中
	 * 'controller' => array(
	 * 		'actionKey' => 'Action', //方法名默认后缀.
	 * 	),
	 * 结果: self::$_actionKey = 'Action'.
	 * </pre>
     * @param string|null $actionKey.
     * @see getActionKey
     */
    public static function setActionKey($actionKey = null)
    {
    	if (null === $actionKey)
    	{
    		$actionKey = self::get('controller', 'actionKey');
    		if (null === $actionKey)
    			$actionKey = 'Action';
    	}
		
    	self::$_actionKey = $actionKey;
    }
    
    /**
     * 获取默认调用的方法名.
     * <pre>
	 * $defaultAction = CControllerConfig::getDefaultAction();
	 * </pre>
     * @return string 默认调用的方法名.
     * @see _setDefaultAction
     */
    public static function getDefaultAction()
    {
    	if (null === self::$_defaultAction)
    		self::_setDefaultAction();
    	
    	return self::$_defaultAction;
    }
    
    /**
     * 设置默认调用的方法名. 如果已经配置, 从配置中获取, 否则默认是'index'.
     * <pre>
	 * CControllerConfig::_setDefaultAction();
	 * 取配置中
	 * 'controller' => array(
	 * 		'defaultAction' => 'index', //如果方法名为空，默认调用的方法名.
	 * 	),
	 * 结果: self::$_defaultAction = 'index'.
	 * </pre>
	 * @see getDefaultAction
     */
    protected static function _setDefaultAction()
    {
    	self::$_defaultAction = self::get('controller', 'defaultAction');
    	if (null === self::$_defaultAction)
    		self::$_defaultAction = 'index';
    }
    
    /**
     * 获取默认调用的控制器类名.
     * <pre>
	 * $defaultController = CControllerConfig::getDefaultController();
	 * </pre>
     * @return string 默认调用的控制器类名.
     * @see _setDefaultController
     */
	public static function getDefaultController()
    {
    	if (null === self::$_defaultController)
    		self::_setDefaultController();
    		
    	return self::$_defaultController;
    }
    
    /**
     * 设置默认调用的控制器类名. 如果已经配置, 从配置中获取, 否则默认是'index'.
     * <pre>
	 * CControllerConfig::_setDefaultController();
	 * 取配置中
	 * 'controller' => array(
	 * 		'defaultController' => 'index', //如果控制器名为空，默认调用的控制器名.
	 * 	),
	 * 结果: self::$_defaultController = 'index'.
	 * @see getDefaultController
     */
    protected static function _setDefaultController()
    {
    	self::$_defaultController = self::get('controller', 'defaultController');
    	if (null === self::$_defaultController)
    		self::$_defaultController = 'index';
    }
    
    /**
     * 获取控制器类所在的目录.
     * <pre>
	 * $controllerDir = CControllerConfig::getControllerDir();
	 * </pre>
     * @return string 控制器类所在的目录.
     * @see setControllerDir
     */
	public static function getControllerDir()
    {
    	if (null === self::$_controllerDir)
    		self::setControllerDir();
    		
    	return self::$_controllerDir;
    }
    
    /**
     * 设置控制器类所在的目录.
     * <pre>
     * $controllerDir = null;
	 * CControllerConfig::setControllerDir($controllerDir);
	 * 如果$controllerDir === null, 取配置中
	 * 'controller' => array(
	 * 		'controllerDir' => APP_DIR . '/controllers', //控制器所在的目录.
	 * 	),
	 * 结果: self::$_controllerDir = APP_DIR . '/controllers'.
     * @param string|null $controllerDir. 如果已经配置, 从配置中获取, 否则默认是 APP_DIR . '/controllers'.
     * @throws CControllerException. 如果控制器类所在的目录不存在, 抛出异常.
     * @see getControllerDir
     */
    public static function setControllerDir($controllerDir = null)
    {
    	if (null === $controllerDir)
    	{
    		$controllerDir = self::get('controller', 'controllerDir');
    		if (null === $controllerDir)
				$controllerDir = APP_DIR . DS . 'controllers';
    	}
		
		if (!is_dir($controllerDir))
			throw new CControllerException('CControllerConfig:setControllerDir controllerDir not exists', array('{controllerDir}' => $controllerDir));
		
		self::$_controllerDir = $controllerDir;
    }
    
    /**
     * 如果出现异常, 则跳转的控制器.
     * <pre>
	 * $errorAction = CControllerConfig::getErrorAction();
	 * 'controller' => array(
     * 		'errorAction' => 'index/error',
	 *	),
	 * 结果: $errorAction = array('IndexController' => 'errorAction');
	 * </pre>
     * @param string|null $errorAction. 如果已经配置, 从配置中获取, 否则默认是array('IndexController' => 'errorAction').
     */
    public static function getErrorAction()
    {
    	$errorAction = self::get('controller', 'errorAction');
    	if (null !== $errorAction && strpos($errorAction, '/'))
			$errorAction = explode('/', $errorAction);
    	else
    		$errorAction = array('Index', 'error');
			
    	$errorAction[0] = ucfirst(strtolower($errorAction[0])) . self::getControllerKey();
    	$errorAction[1] = strtolower($errorAction[1]) . self::getActionKey();
    	
    	require_once self::getControllerDir() . DS . $errorAction[0] . '.php';
    	return $errorAction;
    }
}
